package com.rad.statistics.common.cmd;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import com.google.gson.Gson;
import com.rad.net.protocol.common.annotation.POST;
import com.rad.net.protocol.common.annotation.Transient;
import com.rad.net.protocol.common.cmd.BaseCmd;
import com.rad.statistics.common.Base64;

/**
 * 类说明：统计cmd
 * 
 * @author kalui.huang
 * @date 2014-10-15
 * @version 1.0
 */
public class StatisticsCmd extends BaseCmd {

	private static final long serialVersionUID = 1L;
	private static final int GZIP_SIZE = 5*1024;

	private String IMEI;// 国际移动电话设备识别码
	private String IMSI;// 国际移动用户识别码
	private String phoneType;// 机型
	private String osVersion;// 系统版本
	private String pixel;// 分辨率，格式 width x height
	private String macAddress;// mac地址
	private String osPlatforms;// 系统平台"android","ios"
	private boolean systemApp;//是否是系统app
	private String brand; //品牌
	private String networkType; //联网方式

	@Transient
	private List<String> datas; // Json字符串的链表，Json字符串由BaseEvent子类转化而成

	private boolean gzip; //表示gzipData是否为压缩数据
	@POST
	private String gzipData;// 事件数据，如果gzip为true则表示该字段为压缩数据，反之为原数据;

	/**
	 * 获取手机的IMEI
	 * 
	 * @return 手机的IMEI
	 */
	public String getIMEI() {
		return IMEI;
	}

	/**
	 * 设置手机的IMEI
	 * 
	 * @param IMEI
	 */
	public void setIMEI(String IMEI) {
		this.IMEI = IMEI;
	}

	/**
	 * 获取手机的IMSI
	 * 
	 * @return 手机的IMSI
	 */
	public String getIMSI() {
		return IMSI;
	}

	/**
	 * 设置手机的IMSI
	 * 
	 * @param IMSI
	 */
	public void setIMSI(String IMSI) {
		this.IMSI = IMSI;
	}

	/**
	 * 获取手机的机型
	 * 
	 * @return 手机的机型
	 */
	public String getPhoneType() {
		return phoneType;
	}

	/**
	 * 设置手机的机型
	 * 
	 * @param phoneType
	 */
	public void setPhoneType(String phoneType) {
		this.phoneType = phoneType;
	}

	/**
	 * 获取手机的系统版本
	 * 
	 * @return 手机的系统版本
	 */
	public String getOsVersion() {
		return osVersion;
	}

	/**
	 * 设置手机的系统版本
	 * 
	 * @param osVersion
	 */
	public void setOsVersion(String osVersion) {
		this.osVersion = osVersion;
	}

	/**
	 * 获取手机的屏幕像素
	 * 
	 * @return 手机屏幕像素
	 */
	public String getPixel() {
		return pixel;
	}

	/**
	 * 设置手机的屏幕像素
	 * 
	 * @param pixel
	 */
	public void setPixel(String pixel) {
		this.pixel = pixel;
	}

	/**
	 * 获取手机的MAC地址
	 * 
	 * @return 手机MAC地址
	 */
	public String getMacAddress() {
		return macAddress;
	}

	/**
	 * 设置手机的MAC地址
	 * 
	 * @param macAddress
	 */
	public void setMacAddress(String macAddress) {
		this.macAddress = macAddress;
	}

	/**
	 * 获取手机系统平台
	 * 
	 * @return "android"或者"ios"
	 */
	public String getOsPlatforms() {
		return osPlatforms;
	}

	/**
	 * 设置手机系统平台
	 * 
	 * @param osPlatforms
	 *            "android"或者"ios"
	 */
	public void setOsPlatforms(String osPlatforms) {
		this.osPlatforms = osPlatforms;
	}

	/**
	 * 是否是系统app
	 * @return
	 */
	public boolean isSystemApp() {
		return systemApp;
	}

	/**
	 * 设置该app是否是系统app
	 * @param systemApp
	 */
	public void setSystemApp(boolean systemApp) {
		this.systemApp = systemApp;
	}

	/**
	 * 获取由统计事件所转化成的字符串链表
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<String> getDatas() {
		if (datas == null) {
			if(gzipData != null){
				String jsonStr = gzipData;
				if(gzip){
					jsonStr = uncompress(gzipData);
				}
				datas = new Gson().fromJson(jsonStr, List.class);
			}
		}
		return datas;
	}

	/**
	 * 设置数据
	 * 
	 * @param datas
	 */
	public void setDatas(List<String> datas) {
		this.datas = datas;
	}

	/**
	 * 获取压缩的Json字符串
	 * 
	 * @return
	 */
	public String getGzipData() {
		if (gzipData == null) {
			if (datas != null) {
				String jsonStr = new Gson().toJson(datas);
				if(jsonStr.length() >= GZIP_SIZE){
					gzipData = compress(jsonStr);
					gzip = true;
				} else {
					gzipData = jsonStr;
					gzip = false;
				}
			}
		}
		return gzipData;
	}

	/**
	 * 设置压缩的Json字符串
	 * 
	 * @param gzipData
	 */
	public void setGzipData(String gzipData) {
		this.gzipData = gzipData;
	}

	public void addDatas(List<String> newDatas) {
		if (datas == null) {
			datas = new ArrayList<String>();
		}
		datas.addAll(newDatas);
	}

	/**
	 * 数据是否是压缩状态
	 * @return true表示数据为压缩，false表示数据不压缩
	 */
	public boolean isGzip() {
		return gzip;
	}

	/**
	 * 设置数据压缩状态
	 * @param isGzip
	 */
	public void setGzip(boolean isGzip) {
		this.gzip = isGzip;
	}

	/**
	 *  压缩字符串
	 * 
	 * @param str 需要压缩的json字符串
	 * @return 压缩后的字符串
	 */
	private static String compress(String str) {
		if (str == null || str.length()==0) {
			return str;
		}
		String encode = null;
		ByteArrayOutputStream out = null;
		GZIPOutputStream gzip = null;
		try {
			out = new ByteArrayOutputStream();
			gzip = new GZIPOutputStream(out);
			gzip.write(str.getBytes());
			gzip.finish();
			gzip.flush();
			encode = new String(Base64.encodeBase64(out.toByteArray()));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(gzip != null){
					gzip.close();
				}
				if(out != null){
					out.close();
				}
			} catch(IOException e){
				e.printStackTrace();
			}
		}
		return encode;
	}

	/**
	 * 解压字符串
	 * @param str 待解压的字符串
	 * @return 解压后的json字符串
	 */
	private static String uncompress(String str) {
		if (str == null || str.length()==0) {
			return str;
		}
		String result = null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ByteArrayInputStream bis = null;
		GZIPInputStream gis = null;
		try {
			byte[] src = Base64.decodeBase64(str.getBytes());
			bis = new ByteArrayInputStream(src);
			gis = new GZIPInputStream(bis);
			byte[] buffer = new byte[1024];
			int n = -1;
			while ((n = gis.read(buffer)) != -1) {
				out.write(buffer, 0, n);
			}
			result = new String(out.toByteArray());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try{
				if(out != null){
					out.close();
				}
				if(gis != null){
					gis.close();
				}
				if(bis != null){
					bis.close();
				}
			} catch (IOException e){
				e.printStackTrace();
			}
		}
		return result;
	}

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public String getNetworkType() {
		return networkType;
	}

	public void setNetworkType(String networkType) {
		this.networkType = networkType;
	}
	
}
